﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Device.Location;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Controls.Maps;
using System.Threading;
using Microsoft.Phone.Shell;
using System.IO;
using System.IO.IsolatedStorage;
using Coding4Fun.Phone.Controls;
using System.Collections.ObjectModel;
using System.Net.NetworkInformation;
using GlobalRadar.Language;

namespace GlobalRadar
{
    public partial class MainPage : PhoneApplicationPage
    {
        IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;

        GeoCoordinateWatcher myWatch = new GeoCoordinateWatcher(GeoPositionAccuracy.High);

        UI.AppStatusBar myStatus = new UI.AppStatusBar();

        bool LangVN = false;

        public static Thread RadarScan;

        #region Khai Báo Layer Map

        double angle = 0;

        double RadarZoom = 4.7;

        bool UpdateRoute = false;

        MapDraw mapdraw;

        MapLayer mapPushpin = new MapLayer();

        ApplicationBarController barControl;

        Class.Support obj = new Class.Support();

        #endregion
        // Constructor
        public MainPage()
        {
            InitializeComponent();

            LangVN = App.LangVN;

            MapControl.Children.Clear();

            // Thêm layer để hiển thị các Pushpin
            MapControl.Children.Add(mapPushpin);

            InitializeGPS();

            InitiaizeControl();

            InitializeMap();
            
            if (NetworkInterface.GetIsNetworkAvailable() != true)
            {
                MessageBox.Show(LangVN==true?ResourceVN.NetworkError:ResourceEn.NetworkError);
            }
        }

        private void InitiaizeControl()
        {
            barControl = new ApplicationBarController(this.ApplicationBar);
            
            barControl.AddNewButton(LangVN==true?ResourceVN.Me:ResourceEn.Me, "/icons/Location.png", true, ApplicationBarButton_Click);

            barControl.AddNewButton(LangVN == true ? ResourceVN.Find : ResourceEn.Find, "/icons/appbar.feature.search.rest.png", true, ApplicationBarButton_Click);

            barControl.AddNewButton(LangVN == true ? ResourceVN.Route : ResourceEn.Route, "/icons/Route.png", true, ApplicationBarButton_Click);

            barControl.AddNewButton(LangVN == true ? ResourceVN.Refresh : ResourceEn.Refresh, "/icons/appbar.refresh.rest.png", true, ApplicationBarButton_Click);

            barControl.AddNewMenuItem(LangVN == true ? ResourceVN.deleteDirection : ResourceEn.deleteDirection, true, ApplicationBarMenu_Click);

            barControl.AddNewMenuItem(LangVN == true ? ResourceVN.Login : ResourceEn.Login, true, ApplicationBarMenu_Click);

            barControl.AddNewMenuItem(LangVN == true ? ResourceVN.Group : ResourceEn.Group, true, ApplicationBarMenu_Click);

            barControl.AddNewMenuItem(LangVN == true ? ResourceVN.Logout : ResourceEn.Logout, true, ApplicationBarMenu_Click);

            barControl.AddNewMenuItem(LangVN == true ? ResourceVN.Settings : ResourceEn.Settings, true, ApplicationBarMenu_Click);

            if (LangVN == true)
            {
                barControl.ShowButtons(ResourceVN.Route, ResourceVN.Me, ResourceVN.Find, ResourceVN.Refresh);
                barControl.ShowMenuItems(ResourceVN.Login, ResourceVN.deleteDirection, ResourceVN.Settings);
            }
            else
            {
                barControl.ShowButtons(ResourceEn.Route, ResourceEn.Me, ResourceEn.Find, ResourceEn.Refresh);
                barControl.ShowMenuItems(ResourceEn.Login, ResourceEn.deleteDirection, ResourceEn.Settings);
            }

            mapdraw = new MapDraw(MapControl);

            mapdraw.CreateDataRadar();

            mapdraw.ShowItem("finger", "mapRoute", "circle", "myLocation");
        }

        private void InitializeMap()
        {
            MapControl.ZoomBarVisibility = Visibility.Visible; // Bật thanh Zoom
            MapControl.LogoVisibility = Visibility.Collapsed; // Tắt logo bingmap
            MapControl.CopyrightVisibility = Visibility.Collapsed;// Tắt dòng CopyRight của Bingmap
            // Thiết lập vị trí hiển thị ncuar bản đồ
            MapControl.Center = new GeoCoordinate(16.4575, 107.5840);
            MapControl.SetView(MapControl.Center, 15);
            // Thiết lập tỉ lệ Zoom của map            
            MapControl.ZoomLevel = 15;

            mapdraw.PolygonDraw("circle", myWatch.Position.Location, RadarZoom);

            MapControl.SetView(myWatch.Position.Location, 15);
        }

        private void InitializeGPS()
        {
            myWatch.MovementThreshold = 50;
            myWatch.PositionChanged += (s, e) =>
            {
                mapdraw.PolygonDraw("circle", myWatch.Position.Location, this.RadarZoom);
                mapdraw.PushpinUpdateLocation("myLocation", myWatch.Position.Location);
                MapControl.SetView(myWatch.Position.Location, 15);

                if (UpdateRoute==true)
                {
                    if (mapdraw.GetPushpinLocation("FindLocation") != null)
                    {
                        List<GeoCoordinate> listRouter = new List<GeoCoordinate>();

                        listRouter.Add(myWatch.Position.Location);
                    
                        listRouter.Add(mapdraw.GetPushpinLocation("FindLocation"));

                        GetRouteLine(listRouter);
                    }
                }
                if (settings.Contains("Login")==true)
                {
                    if ((bool)settings["Login"] == true)
                    {
                        if (NetworkInterface.GetIsNetworkAvailable() == true)
                        {
                            mySQLService.RadarServicePortTypeClient client = new mySQLService.RadarServicePortTypeClient();

                            client.UpdateLocationAsync(Global.UserInfo.UserID, e.Position.Location.Latitude, e.Position.Location.Longitude, "");
                        }
                    }
                }
            };
            myWatch.StatusChanged += (s, e) =>
            {
                switch (e.Status)
                {
                    case GeoPositionStatus.NoData:
                    case GeoPositionStatus.Disabled:
                        MessageBox.Show(LangVN == true ? ResourceVN.NetworkError : ResourceEn.NetworkError);
                        break;
                    case GeoPositionStatus.Initializing:
                        break;
                    case GeoPositionStatus.Ready:
                        break;
                }
            };
            myWatch.Start();
            // Khởi tạo vòng xoay kim đồng hồ 

            RadarScan = new Thread((ThreadStart)delegate()
            {
                double UpdateLocationTracking = 0.0;

                while (true)
                {
                    Thread.Sleep(30);

                    UpdateLocationTracking += 30;

                    Dispatcher.BeginInvoke(() => DrawLineRadar(myWatch.Position.Location,this.RadarZoom, angle));

                    angle += 1;
                    if (angle >= 360) angle = 0;

                    if (UpdateLocationTracking >= 10000)
                    {
                        Dispatcher.BeginInvoke(() => obj.GetAllPushpinGroupMe(mapdraw, Global.UserInfo.UserID));

                        UpdateLocationTracking = 0;
                    }
                }
            });
            RadarScan.Start();
        }

        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {            
            if(settings==null) return;

            if (settings.Contains("Login"))
            {
                if ((bool)settings["Login"] == true)
                {
                    if (LangVN == true)
                    {
                        barControl.ShowMenuItems(ResourceVN.Login, ResourceVN.deleteDirection, ResourceVN.Settings);
                        barControl.ShowMenuItems(ResourceVN.Group,ResourceVN.Logout,ResourceVN.deleteDirection,ResourceVN.Settings);
                    }
                    else
                    {
                        barControl.ShowMenuItems(ResourceEn.Login, ResourceEn.deleteDirection, ResourceEn.Settings);
                        barControl.ShowMenuItems(ResourceEn.Group, ResourceEn.Logout, ResourceEn.deleteDirection, ResourceEn.Settings);
                    }
                    if (NetworkInterface.GetIsNetworkAvailable() == true)
                    {
                        obj.GetAllPushpinGroupMe(mapdraw, Global.UserInfo.UserID);
                    };
                }
                else
                {
                    if (LangVN == true)
                    {
                        barControl.RemoveMenuItems(ResourceVN.Group, ResourceVN.Logout, ResourceVN.Settings);
                        barControl.ShowMenuItems(ResourceVN.Login, ResourceVN.deleteDirection, ResourceVN.Settings);
                    }
                    else
                    {
                        barControl.RemoveMenuItems(ResourceEn.Group, ResourceEn.Logout, ResourceEn.Settings);
                        barControl.ShowMenuItems(ResourceEn.Login, ResourceEn.deleteDirection, ResourceEn.Settings);
                    }
                }
            }

            if (settings.Contains("MapView"))
            {
                if ((bool)settings["MapView"] == true)
                {
                    MapControl.Mode = new AerialMode(true);
                }
                else
                {
                    MapControl.Mode = new RoadMode();
                }
            }

            if (settings.Contains("RadarZoom"))
            {
                double Zoomvalue;

                if (double.TryParse(settings["RadarZoom"].ToString(), out Zoomvalue))
                {
                    RadarZoom = Zoomvalue;
                    mapdraw.PolygonDraw("circle", myWatch.Position.Location, this.RadarZoom);
                    DrawLineRadar(myWatch.Position.Location, this.RadarZoom, angle);
                }
                else
                    Zoomvalue = 4.7;
            }
            else
                settings.Add("RadarZoom", this.RadarZoom);
            

            base.OnNavigatedTo(e);
        }

        void DrawLineRadar(GeoCoordinate location, double Zoom, double angle)
        {
            if (location == null) return;

            var earthRadius = 6371;
            var lat = myWatch.Position.Location.Latitude * Math.PI / 180.0; //radians 
            var lon = myWatch.Position.Location.Longitude * Math.PI / 180.0; //radians 
            var d = myWatch.Position.Location.HorizontalAccuracy / Zoom / earthRadius; // d = angular distance covered on earths surface 

            var brng = angle * Math.PI / 180.0; //radians 
            var latRadians = Math.Asin(Math.Sin(lat) * Math.Cos(d) + Math.Cos(lat) * Math.Sin(d) * Math.Cos(brng));
            var lngRadians = lon + Math.Atan2(Math.Sin(brng) * Math.Sin(d) * Math.Cos(lat), Math.Cos(d) - Math.Sin(lat) * Math.Sin(latRadians));

            var pt = new GeoCoordinate(180.0 * latRadians / Math.PI, 180.0 * lngRadians / Math.PI);

            mapdraw.PolyLineDraw("finger", myWatch.Position.Location, pt);

        }

        private void ApplicationBarMenu_Click(object sender, EventArgs e)
        {
            ApplicationBarMenuItem btn = (ApplicationBarMenuItem)sender;

            string text = btn.Text.ToLower();

            if (text == (LangVN == true ? ResourceVN.Settings.ToLower() : ResourceEn.Settings.ToLower()))
            {
                NavigationService.Navigate(new Uri("/UI/AppSettings.xaml",UriKind.RelativeOrAbsolute));
            }
            if (text == (LangVN == true ? ResourceVN.Login.ToLower() : ResourceEn.Login.ToLower()))
            {
                NavigationService.Navigate(new Uri("/UI/AppLogin.xaml",UriKind.RelativeOrAbsolute));
            }
            if (text == (LangVN == true ? ResourceVN.Group.ToLower() : ResourceEn.Group.ToLower()))
            {
                NavigationService.Navigate(new Uri("/UI/AppGroupManager.xaml", UriKind.RelativeOrAbsolute));
            }
            if (text == (LangVN == true ? ResourceVN.Logout.ToLower() : ResourceEn.Logout.ToLower()))
            {
                if (LangVN == true)
                {
                    barControl.RemoveMenuItems(ResourceVN.Group, ResourceVN.Logout, ResourceVN.Settings);
                    barControl.ShowMenuItems(ResourceVN.Login, ResourceVN.deleteDirection, ResourceVN.Settings);
                }
                else
                {
                    barControl.RemoveMenuItems(ResourceEn.Group, ResourceEn.Logout, ResourceEn.Settings);
                    barControl.ShowMenuItems(ResourceEn.Login, ResourceEn.deleteDirection, ResourceEn.Settings);
                }
                if (settings.Contains("Login"))
                {
                    settings["Login"] = false;
                }
                Global.DeleteSettings();
            }
            if (text == (LangVN == true ? ResourceVN.deleteDirection.ToLower() : ResourceEn.deleteDirection.ToLower()))
            {
                mapdraw.RemoveItem("mapRoute");
                UpdateRoute = false;
            }
        }

        private void ApplicationBarButton_Click(object sender, EventArgs e)
        {
            ApplicationBarIconButton btn = (ApplicationBarIconButton)sender;

            string text = btn.Text.ToLower();

            if (text == (LangVN == true ? ResourceVN.Me.ToLower() : ResourceEn.Me.ToLower()))
            {
                MapControl.Center = myWatch.Position.Location;
            }
            if (text == (LangVN == true ? ResourceVN.Refresh.ToLower() : ResourceEn.Refresh.ToLower()))
            {
                MapControl.Center = myWatch.Position.Location;

                obj.GetAllPushpinGroupMe(mapdraw, Global.UserInfo.UserID);
            }

            if (text == (LangVN == true ? ResourceVN.Find.ToLower() : ResourceEn.Find.ToLower()))
            {
                mapdraw.RemoveItem("FindLocation");
                InputPrompt input = new InputPrompt();
                input.Completed += (s, args) =>
                {
                    SearchLocationAdress(args.Result);
                };
                input.Title = LangVN==true?ResourceVN.FindTitle:ResourceEn.FindTitle;
                input.Message = LangVN==true?ResourceVN.FindContent:ResourceEn.FindContent;
                input.Show();
            }

            if (text == (LangVN == true ? ResourceVN.Route.ToLower() : ResourceEn.Route.ToLower()))
            {
                mapdraw.RemoveItem("FindLocation");
                InputPrompt input = new InputPrompt();
                input.Completed += (s, args) =>
                {
                    RouteMetoLocation(args.Result);
                };
                input.Title = LangVN == true ? ResourceVN.RouteTitle : ResourceEn.RouteTitle;
                input.Message = LangVN == true ? ResourceVN.RouteContent : ResourceEn.RouteContent;
                input.Show();
            }           
        }

        private void SearchLocationAdress(string Address)
        {
            if (NetworkInterface.GetIsNetworkAvailable() != true) return;
                        
            if (Address == "") return;

            BingMapGeocode.GeocodeRequest geocodeRequest = new BingMapGeocode.GeocodeRequest();
            geocodeRequest.Credentials = new Microsoft.Phone.Controls.Maps.Credentials();
            geocodeRequest.Credentials.ApplicationId = "Ah04k4eCmb7IC1gG50_ToWNRSBrBcx2CBCumfzID0bI1bRvUKEDt2y6r1Htpo6kG";

            geocodeRequest.Query = Address.Trim();

            BingMapGeocode.FilterBase[] filter = new BingMapGeocode.FilterBase[1];
            filter[0] = new BingMapGeocode.ConfidenceFilter() { MinimumConfidence = BingMapGeocode.Confidence.High };
            BingMapGeocode.GeocodeOptions geocodeOptions = new BingMapGeocode.GeocodeOptions();
            geocodeOptions.Filters = new ObservableCollection<BingMapGeocode.FilterBase>(filter);
            geocodeRequest.Options = geocodeOptions;
            BingMapGeocode.GeocodeServiceClient geocodeService = new BingMapGeocode.GeocodeServiceClient("BasicHttpBinding_IGeocodeService");
            geocodeService.GeocodeCompleted += (s, e) =>
            {
                List<Microsoft.Phone.Controls.Maps.Pushpin> pushpins = new List<Microsoft.Phone.Controls.Maps.Pushpin>();

                if (e.Result.Results.Count > 0)
                {
                    mapdraw.ShowItem("FindLocation");
                    mapdraw.PushpinUpdateLocation("FindLocation", e.Result.Results[0].Locations[0]);
                    MapControl.Center = e.Result.Results[0].Locations[0];
                }
                else
                    MessageBox.Show(LangVN == true ? ResourceVN.ArletResultFound : ResourceEn.ArletResultFound);
            };
            geocodeService.GeocodeAsync(geocodeRequest);
        }

        private void RouteMetoLocation(string Address)
        {
            if (NetworkInterface.GetIsNetworkAvailable() != true) return;

            if (Address == "") return;

            myStatus.ShowPopup(LangVN == true ? ResourceVN.WaitGetLocation : ResourceEn.WaitGetLocation);

            BingMapGeocode.GeocodeRequest geocodeRequest = new BingMapGeocode.GeocodeRequest();
            geocodeRequest.Credentials = new Microsoft.Phone.Controls.Maps.Credentials();
            geocodeRequest.Credentials.ApplicationId = "Ah04k4eCmb7IC1gG50_ToWNRSBrBcx2CBCumfzID0bI1bRvUKEDt2y6r1Htpo6kG";

            geocodeRequest.Query = Address.Trim();

            BingMapGeocode.FilterBase[] filter = new BingMapGeocode.FilterBase[1];
            filter[0] = new BingMapGeocode.ConfidenceFilter() { MinimumConfidence = BingMapGeocode.Confidence.High };
            BingMapGeocode.GeocodeOptions geocodeOptions = new BingMapGeocode.GeocodeOptions();
            geocodeOptions.Filters = new ObservableCollection<BingMapGeocode.FilterBase>(filter);
            geocodeRequest.Options = geocodeOptions;
            BingMapGeocode.GeocodeServiceClient geocodeService = new BingMapGeocode.GeocodeServiceClient("BasicHttpBinding_IGeocodeService");
            geocodeService.GeocodeCompleted += (s, e) =>
            {
                List<Microsoft.Phone.Controls.Maps.Pushpin> pushpins = new List<Microsoft.Phone.Controls.Maps.Pushpin>();

                if (e.Result.Results.Count > 0)
                {
                    List<GeoCoordinate> locations = new List<GeoCoordinate>();
                    locations.Add(myWatch.Position.Location);
                    locations.Add(e.Result.Results[0].Locations[0]);

                    GetRouteLine(locations);

                    mapdraw.ShowItem("FindLocation");
                    mapdraw.PushpinUpdateLocation("FindLocation", e.Result.Results[0].Locations[0]);
                    MapControl.Center = e.Result.Results[0].Locations[0];

                    UpdateRoute = true;
                }
                else
                    MessageBox.Show(LangVN == true ? ResourceVN.ArletResultFound : ResourceEn.ArletResultFound);
                myStatus.Abort();
            };
            geocodeService.GeocodeAsync(geocodeRequest);
        }

        private void GetRouteLine(List<GeoCoordinate> locations)
        {
            if (NetworkInterface.GetIsNetworkAvailable() != true) return;

            MapLayer RouteLayer = new MapLayer();

            BingMapRoute.RouteServiceClient routeService = new BingMapRoute.RouteServiceClient("BasicHttpBinding_IRouteService");

            routeService.CalculateRouteCompleted += (sender, e) =>
            {
                var points = e.Result.Result.RoutePath.Points;

                var coordinates = points.Select(x => new GeoCoordinate(x.Latitude, x.Longitude));

                var routeColor = Colors.Blue;

                var routeBrush = new SolidColorBrush(routeColor);

                var routeLine = new MapPolyline()
                {
                    Locations = new LocationCollection(),
                    Stroke = routeBrush,
                    Opacity = 0.65,
                    StrokeThickness = 5.0,
                };

                foreach (var location in points)
                {
                    routeLine.Locations.Add(new GeoCoordinate(location.Latitude, location.Longitude));
                }
                //RouteLayer.Children.Add(routeLine);
                mapdraw.UpdateMaplayer("mapRoute", routeLine);
                mapdraw.ShowItem("mapRoute");
            };

            routeService.CalculateRouteAsync(new BingMapRoute.RouteRequest()
            {
                Credentials = new Credentials()
                {
                    ApplicationId = "Ah04k4eCmb7IC1gG50_ToWNRSBrBcx2CBCumfzID0bI1bRvUKEDt2y6r1Htpo6kG"
                },
                Options = new BingMapRoute.RouteOptions()
                {
                    RoutePathType = BingMapRoute.RoutePathType.Points
                },
                Waypoints = new ObservableCollection<BingMapRoute.Waypoint>(
                    locations.Select(x => new BingMapRoute.Waypoint()
                    {
                        Location = x
                    }))
            });
        }

        private void BarControl_BackKeyPress(object sender, System.ComponentModel.CancelEventArgs e)
        {
            MessageBoxResult Result = MessageBox.Show("Bạn chắc chắn thoát chứ?", "thoát ứng dụng", MessageBoxButton.OKCancel);

            if (Result == MessageBoxResult.Cancel)

                e.Cancel = true;
            else
            {
                if (NavigationService.CanGoBack)
                {
                    while (NavigationService.RemoveBackEntry() != null)
                    {
                        Global.SaveSettings();

                        NavigationService.RemoveBackEntry();
                    }
                }
            }
        }
    }
}